package com.jack.payment.aspect;


import com.jack.payment.aspect.common.AspectHandlerUtil;
import com.jack.payment.constant.ResultHintConstant;
import com.jack.payment.entity.business.UriDescribeBo;
import com.jack.payment.entity.common.BusinessException;
import com.jack.payment.entity.common.CommonAskHead;
import com.jack.payment.entity.common.CommonAskParam;
import com.jack.payment.entity.common.CommonResult;
import com.jack.payment.entity.mong.RequestLogModel;
import com.jack.payment.rabbitmq.RabbitQueueSendUtil;
import com.jack.payment.service.basic.impl.UserServiceImpl;
import com.jack.payment.token.util.TokenUtil;
import com.jack.payment.util.common.StringUtil;
import com.jack.payment.util.network.NetworkUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;

@Aspect
@Order(1)
@Component
public class ResultAdminAspect {
    private Logger log = LoggerFactory.getLogger(ResultAdminAspect.class);

    /**登录 与 一些初始化接口, 包名路径*/
    private static final String LOGIN_MODULE_PATH = "com.jack.payment.controller.admin.noauth";
    /**管理端*/
    private static final String ADMIN_MODULE_PATH = "com.jack.payment.controller.admin.auth";


    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private AspectHandlerUtil aspectHandler;
    @Autowired
    private TokenUtil tokenUtil;
    @Autowired
    private RabbitQueueSendUtil rabbitQueueSendUtil;



    @Pointcut("execution(* com.jack.payment.controller.admin..*(..))")
    public void executeService(){
    }

    @Around("executeService()")
    public CommonResult doAround(ProceedingJoinPoint pjp) throws Throwable {
        //接口请求开始时间
        Long startRequestTime = System.currentTimeMillis();
        // 获取请求数据
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取类包名
        String pageName = pjp.getTarget().getClass().getPackage().getName();
        // 方法获取方法名
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        // api 接口
        String uri = request.getRequestURI();
        // 获取请求参数
        Object[] args = pjp.getArgs();
        // 返回值
        CommonResult resultParam = new CommonResult();
        // 请求值
        CommonAskParam param = new CommonAskParam();
        // 用户id
        String userId = "";
        Integer status = 1;
        String message = "";
        String requestIp = NetworkUtil.getIPAddress(request);
        UriDescribeBo uriDescribeModel = new UriDescribeBo(uri, "未知的接口");
        // 请求区分 [0 : login, 1: ADMIN, 2: WEBHOOK, 3.API]
        Integer requestType = 0;
        try {
            uriDescribeModel = aspectHandler.getUriDetail(method, uri);
            // 登录
            if (LOGIN_MODULE_PATH.equals(pageName)) {
                param = (CommonAskParam) args[0];
                CommonAskHead headParam = param.getCommon();
                headParam.setIpAddress(requestIp);
                headParam.setCurrentTime(startRequestTime / 1000);
                param.setCommon(headParam);
                args[0] = param;
                resultParam = (CommonResult) pjp.proceed(args);
            }
            // 管理
            if (ADMIN_MODULE_PATH.equals(pageName)) {
                // 值的交换
                param = (CommonAskParam) args[0];
                CommonAskHead headParam = param.getCommon();
                userId = (String) param.getCommon().getUserId();
                headParam.setUserId(userService.getAppointIdAccountInfo(userId));       // 查询出用户
                param.setCommon(headParam);                                             // 将查询用户返回给切面点
                args[0] = param;
                String newToken = adminClassJudgeVerify(request.getHeader("token"), userId);
                resultParam = (CommonResult) pjp.proceed(args);
                resultParam.setToken(newToken);
                requestType = 1;
            }
        } catch (Exception e) {
            log.error("记录日志错误"+ e);
            resultParam = aspectHandler.exceptionClassJudgeVerify(uri, e);
            message = resultParam.getMessage();
            status = 0;
        } finally {
            param.getCommon().setUserId(userId);
            args[0] = param;
            sendRequestToQueueMessage(
                    requestType, startRequestTime,
                    uriDescribeModel, request, args,
                    status, param, userId, message, requestIp
                    );
        }
        return resultParam;
    }


    /**
     * 特殊模块需要验证 token 信息
     * @param token
     * @param userId
     * @return
     * @throws BusinessException
     */
    public String adminClassJudgeVerify(String token,
                                        String userId) throws BusinessException{
        if (StringUtil.isEmpty(token)) {
            log.warn("admin 模块, 需验证token, 但用户未携带token 数据");
            throw new BusinessException(ResultHintConstant.RELOAD_LOGIN);
        }
        String newToken = tokenUtil.isDeassignToken(token, "admin", userId);
        if (StringUtil.isEmpty(newToken)) {
            log.warn("新生成token失败");
            throw new BusinessException(ResultHintConstant.SYSTEM_CODE);
        }
        return newToken;
    }

    /**
     * 发送消息队列
     */
    public void sendRequestToQueueMessage(Integer requestType, Long startTime,
                                          UriDescribeBo uriDescribe, HttpServletRequest request,
                                          Object[] args, Integer status,
                                          CommonAskParam commonAskParam,
                                          String userId, String message,
                                          String requestIp
                                          )  {
        RequestLogModel requestLogModel = aspectHandler.builderRequestLogModel(requestType, startTime, uriDescribe,
                request, args, requestIp, status, message);
        CommonAskHead head = commonAskParam.getCommon();
        requestLogModel.setDeviceId(head.getDeviceId() == null ? "" : head.getDeviceId());
        requestLogModel.setDeviceModel(head.getDeviceModel());
        requestLogModel.setOsAppVersion(head.getOsAppVersion());
        requestLogModel.setPageName(head.getPageName());
        requestLogModel.setAppVersion(head.getAppVersion());
        requestLogModel.setLanguage(request.getHeader("language") == null ? 0 : Integer.valueOf(request.getHeader("language")));
        requestLogModel.setToken(request.getHeader("token"));
        requestLogModel.setUserId(userId);
        try {
            rabbitQueueSendUtil.requestLogQueueMessage(requestLogModel);
        } catch (BusinessException e) {
            log.error("消息队列发送失败!!! " + e);
        }
    }
}
